﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading;
using T.ServiceFramework.Spi;
using T.ServiceComponent.Error;

using System.Threading.Tasks;


#if NET451_OR_GREATER
using System.Web.Http;
using System.Web.Http.SelfHost;
#endif

#if NET6_0_OR_GREATER
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using T.ServiceComponent.Cluster.SPI;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore;
using System.IO;
using System.Reflection;
using T.ServiceFramework.Service;
using Microsoft.Extensions.Logging;

#endif

namespace T.SF.Console
{
    internal class HttpSelfHost
    {
        private static HttpSelfHost current = null;
        private static readonly object lckobject = new object();

        private bool isStart = false;

        public static HttpSelfHost Current
        {
            get
            {
                if (current == null)
                {
                    lock (lckobject)
                    {
                        if (current == null)
                            current = new HttpSelfHost();
                    }
                }
                return current;
            }
        }

        private HttpSelfHost()
        {
        }

        public event HttpHostStartedEventHandler OnStarted;
        public event HttpHostStopedEventHandler OnStoped;

#if NET451_OR_GREATER
        private HttpSelfHostServer server_NetF = null;
#endif

#if NET6_0_OR_GREATER
        private IWebHost server = null;
#endif

        public async Task Start(Binding bindInfo, string[] args = null)
        {
            T.ServiceFramework.Service.WebHostService.Current.Load();
            if (isStart)
                throw new TException(SFErrorCode.InvalideOperate, "Service have started.");
            var host = string.Empty;
            if (bindInfo == null)
            {
                host = AppConfig.GetSGHostAddress();
            }
            else
            {
                host = $"http://*:{bindInfo.Port}";
            }

#if NET451_OR_GREATER
            var config = new HttpSelfHostConfiguration(host);
            
            config.Routes.MapHttpRoute( "API Default", "api/{controller}/{id}", new { id = RouteParameter.Optional });
            server_NetF = new HttpSelfHostServer(config);
            server_NetF.OpenAsync().Wait();
#endif

#if NET6_0_OR_GREATER
            try
            {
                var contentRoot = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
                server = WebHost.CreateDefaultBuilder(args)
                                .UseUrls(host)
                                .ConfigureLogging(builder =>
                                    builder.ClearProviders()
                                 )
                                .UseContentRoot(contentRoot)
                                .UseStartup<HostStartup>()
                                .Build();

                await server.RunAsync();
                isStart = true;
            }
            catch (Exception ex)
            {
                isStart = false;
                MonitorProvider.ReportFatalErrorAndLog("WebHost Start Error!", ex);
            }
#endif


            if (OnStarted != null)
                OnStarted(host);
        }

        public void Stop()
        {
            isStart = false;

#if NET451_OR_GREATER
           if(server_NetF!= null)
           {
                 server_NetF.Dispose();
                 server_NetF = null;
            }             
#endif

#if NET6_0_OR_GREATER
            server?.StopAsync().GetAwaiter().GetResult();
            current = null;
#endif

            if (OnStoped != null)
                OnStoped();
        }

    }
}
